package com.leyou.user.service;

import com.leyou.common.enums.ExceptionEnum;
import com.leyou.common.exceptions.LyException;
import com.leyou.common.utils.BeanHelper;
import com.leyou.common.utils.NumberUtils;
import com.leyou.user.entity.User;
import com.leyou.user.mapper.UserMapper;
import com.leyou.user.pojo.UserDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import static com.leyou.common.constants.MQConstants.Exchange.SMS_EXCHANGE_NAME;
import static com.leyou.common.constants.MQConstants.RoutingKey.VERIFY_CODE_KEY;

@Service
@Slf4j
public class UserService {

    @Autowired
    private UserMapper userMapper;

    public Boolean checkData(String data, Integer type) {
        User record = new User();
        switch (type) {
            case 1:
                record.setUsername(data);
                log.info("要验证用户名的一致性,要验证的用户名为:{}", data);
                break;
            case 2:
                log.info("要验证手机号的一致性,要验证的手机号为:{}", data);
                record.setPhone(data);
                break;
            default:
                log.error("请求参数的之一type值错误，传入值为：{}，需要1，2", type);
                throw new LyException(ExceptionEnum.INVALID_REQUEST_PARAM);

        }

        //根据查询条件统计，发现有数据，说明已经存在，则不可以使用
        boolean flag = false;
        try {
            flag = this.userMapper.selectCount(record) != 1;
            if (flag) {
                log.info("验证通过可以使用");
            } else {
                log.info("验证失败，不能使用");
            }
        } catch (Exception e) {
            throw new LyException(ExceptionEnum.DATA_SERVER_ERROR);
        }


        return flag;
    }

    @Autowired
    private AmqpTemplate amqpTemplate;

    @Autowired
    private StringRedisTemplate redisTemplate;

    public void sendVerify(String phone) {

        Map<String, String> msg = new HashMap<>();
        msg.put("phone", phone);
        //生成一个随机数
        String code = NumberUtils.generateCode(6);
        msg.put("code", code);
        //发送消息
        amqpTemplate.convertAndSend(SMS_EXCHANGE_NAME, VERIFY_CODE_KEY, msg);

        //把发送的验证码保存的redis
        redisTemplate.opsForValue().set(phone, code, 5, TimeUnit.MINUTES);
    }

    @Autowired
    private BCryptPasswordEncoder passwordEncoder;

    public void register(User user, String code) {

        String key = user.getPhone();

        //先要进行验证码的校验，
        //判断验证码是否存在，如果存在再去获取验证,不存在或者不匹配，说明给定的参数有问题
        if (!redisTemplate.hasKey(key) || !redisTemplate.opsForValue().get(key).equals(code)) {
            throw new LyException(ExceptionEnum.INVALID_REQUEST_PARAM);
        }


        //对user信息进行加密
        user.setPassword(passwordEncoder.encode(user.getPassword()));
        //保存user，主键回显
        int count = this.userMapper.insertSelective(user);

        if (1 != count) {
            throw new LyException(ExceptionEnum.DATA_SAVE_ERROR);
        }
        //用户注册完成后，应该删除redis中存放的验证码，
        //判断这个对应的key是否还有效，然后，如果有效，则判断过期时间是否大于3秒
        if (redisTemplate.hasKey(key) && redisTemplate.getExpire(key,TimeUnit.SECONDS) > 3) {
            redisTemplate.delete(key);
        }
    }

    public UserDTO queryUserByNameAndPass(String username, String password) {

        User record = new User();
        record.setUsername(username);

        User user = this.userMapper.selectOne(record);

        //判断用户是否为空，验密，先要更具加密后的密码推断盐值，然后拿着盐值和密码 的明文，加密次数，对输入的明文密码加密，得到新的密码然后比较
        if (null==user||passwordEncoder.matches(password,user.getPassword())){
            throw new LyException(ExceptionEnum.INVALID_USERNAME_PASSWORD);
        }
        return BeanHelper.copyProperties(user,UserDTO.class);
    }
}
